<?php
/**
 * Singleton instance of this class represents all messages of the application for a user.
 * There are 4 severity levels - debug, info, warning and error.
 * The instance lives in an HTML session and messages are cleared after being writen to an HTML output.
 * The class is designed as a singleton factory, to be easily accessible everywhere.
 * 
 * @author jan
 */
class Messages {

    private $debugMsgs = array();
    private $infoMsgs = array();
    private $warningMsgs = array();
    private $errorMsgs = array();
    private static $instance;

    public static function instance() {
        if (! self::$instance) {
            $sessionData = SessionData::instance();
            self::$instance = $sessionData->getMessages();
            if (! self::$instance) {
                self::$instance = new Messages();
                $sessionData->setMessages(self::$instance);
            }
        }
        return self::$instance;
    }

    private function makeMessage($msg, $msgArgs) {
        $msgParams = array();
        for ($i = 1; $i < count($msgArgs); $i++) {
            $param = $msgArgs[$i];
            // If the parameter does not contain spaces and it contains one dot,
            // it is probably a key for localization.
            if (strpos($param, ' ') === FALSE && substr_count($param, '.') === 1 && strpos($param, '@') === FALSE) {
                $param = text::get($param);
                if (is_string($param)) {
                    $msgParams[] = $param;
                }
                else {
                    // If it was not a key, use it as it is.
                    $msgParams[] = $msgArgs[$i];
                }
            }
            else {
                $msgParams[] = $param;
            }
        }
        $message = text::get($msg, $msgParams);
        if (! is_string($message)) {
            $message = '!!!' . $msg . '!!!';
        }
        return $message;
    }

    public function debug($msg) {
        $msgArgs = func_get_args();
        $this->debugMsgs[] = $this->makeMessage($msg, $msgArgs);
    }

    public function info($msg) {
        $msgArgs = func_get_args();
        $this->infoMsgs[] = $this->makeMessage($msg, $msgArgs);
    }

    public function warning($msg) {
        $msgArgs = func_get_args();
        $this->warningMsgs[] = $this->makeMessage($msg, $msgArgs);
    }

    public function error($msg) {
        $msgArgs = func_get_args();
        $this->errorMsgs[] = $this->makeMessage($msg, $msgArgs);
    }

    public function hasErrors() {
        return count($this->errorMsgs) > 0;
    }

    public function hasMessages() {
        return count($this->debugMsgs) + count($this->infoMsgs)
                + count($this->warningMsgs) + count($this->errorMsgs) > 0;
    }

    private function prepareForOutput($message) {
        $message = nl2br(html::specialchars($message));
        return $message;
        // return preg_replace("/&#039;(.+)&#039;/", '<em>\1</em>', $message);
    }

    public function printMessages() {
        // Write the DIV element always - we may need it
        // for writing messages from AJAX request.
        echo '<div class="messages" ';
        if (! $this->hasMessages()) {
            echo 'style="display:none"';
        }
        echo '>';

        echo '<div class="messagesRollerUp" onclick="toggleMessages(this)"></div>';

        if ($this->hasMessages()) {
            if (count($this->debugMsgs) > 0) {
                echo '<ul class="debugMessages">';
                foreach ($this->debugMsgs as $msg) {
                    echo '<li>' . $this->prepareForOutput($msg) . '</li>';
                }
                echo '</ul>';
            }
            if (count($this->infoMsgs) > 0) {
                echo '<ul class="infoMessages">';
                foreach ($this->infoMsgs as $msg) {
                    echo '<li>' . $this->prepareForOutput($msg) . '</li>';
                }
                echo '</ul>';
            }
            if (count($this->warningMsgs) > 0) {
                echo '<ul class="warningMessages">';
                foreach ($this->warningMsgs as $msg) {
                    echo '<li>' . $this->prepareForOutput($msg) . '</li>';
                }
                echo '</ul>';
            }
            if (count($this->errorMsgs) > 0) {
                echo '<ul class="errorMessages">';
                foreach ($this->errorMsgs as $msg) {
                    echo '<li>' . $this->prepareForOutput($msg) . '</li>';
                }
                echo '</ul>';
            }

            $this->debugMsgs = array();
            $this->infoMsgs = array();
            $this->warningMsgs = array();
            $this->errorMsgs = array();
        }
        echo '</div>';
    }

    public function messagesForAjax() {
        $jsCode = '';
        if ($this->hasMessages()) {
            if (count($this->debugMsgs) > 0) {
                $jsCode .= 'ajaxResponse.errorMsgs = ' . json_encode($this->debugMsgs) . ';';
            }
            if (count($this->infoMsgs) > 0) {
                $jsCode .= 'ajaxResponse.infoMsgs = ' . json_encode($this->infoMsgs) . ';';
            }
            if (count($this->warningMsgs) > 0) {
                $jsCode .= 'ajaxResponse.warningMsgs = ' . json_encode($this->warningMsgs) . ';';
            }
            if (count($this->errorMsgs) > 0) {
                $jsCode .= 'ajaxResponse.errorMsgs = ' . json_encode($this->errorMsgs) . ';';
            }

            $this->debugMsgs = array();
            $this->infoMsgs = array();
            $this->warningMsgs = array();
            $this->errorMsgs = array();
        }
        return $jsCode;
    }
}
